#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>

#include "Protocol.pb.h"

using boost::asio::ip::udp;
udp::socket *mSocket;

void receiver()
{
    udp::endpoint receiver_endpoint;
    while(1)
    {
        try
        {
            boost::array<char, 1024> recv_buf2;
            size_t len = mSocket->receive_from(
                                 boost::asio::buffer(recv_buf2), receiver_endpoint);
                    std::cout<<recv_buf2.data()<<std::endl;
                    //std::cout<<receiver_endpoint.port()<<std::endl;
            for(int x = 0; x< recv_buf2.size();++x)
            {
                recv_buf2[x] = '\0';
            }
        }
        catch(std::exception& e)
        {
            //std:cout<<e.what()<<std::endl;
        }
    }
}
int main(int argc, char* argv[])
{
    try
    {
        boost::asio::io_service io_service;
        std::string ip;
        int port;
        std::string user;
        std::string login;
        std::cout<<"server ip:";
        std::cin>>ip;
        std::cout<<std::endl<<"server port:";
        std::cin>>port;
        std::cout<<std::endl;
        std::cout<<"login:";
        std::cin>>user;
        login = "user:"+user;
        std::cout<<std::endl;
        Data* mData = new Data();
        mData->set_id(154);
        //mData->mutable_position()->set_x(123);
        //mData->mutable_position()->set_y(456);
        //mData->mutable_position()->set_z(789);
        mData->set_name("alex");
        mData->set_chat("aeeeeeeeee");
        mData->set_command("./configure");
        std::string mParsed;
        mParsed = mData->SerializeAsString();
        std::cout<<"SIZE:"<<mParsed.size()<<std::endl;
        std::cout<<"DATA:"<<mParsed.data()<<std::endl;
        //mData.set_


        udp::endpoint server_endpoint (boost::asio::ip::address_v4::from_string(ip), port);

        mSocket = new udp::socket(io_service);
        mSocket->open(udp::v4());

        /*boost::array<char*, 1> send_buf;
            send_buf.assign((char*)login.data());*/
            mSocket->send_to(boost::asio::buffer(mParsed.data(),mParsed.size()), server_endpoint);

/*
        std::cout<<"client ip:";
        std::cin>>ip;
        std::cout<<std::endl;"client port:";
        std::cin>>port;
        std::cout<<std::endl;
        udp::endpoint send_to(boost::asio::ip::address_v4::from_string(ip), port);

        socket.send_to(boost::asio::buffer(recv_buf2,len), send_to);
        std::cout<<"Users - IP - Port"<<std::endl;
        boost::array<char, 1024> recv_buf;

        udp::endpoint sender_endpoint;
        size_t len = socket.receive_from(
                         boost::asio::buffer(recv_buf), sender_endpoint);*/
        //std::cout.write(recv_buf.data(), len);

        /*int maxuser = atoi(recv_buf.data());
        std::cout<<*recv_buf.data()<<std::endl;
        //recv_buf.assign();
        boost::array<char, 1024> recv_buf2;
        for(int x = 0; x< maxuser;++x)
        {
            size_t len = socket.receive_from(
                         boost::asio::buffer(recv_buf2), server_endpoint);
            std::cout<<recv_buf2.data()<<std::endl;
        }*/
        boost::thread t(&receiver);
        std::cout<<"commands:\nhelp: show this\ngetu:get users from server\nsend: prompt to send messages\n[ip]: endpoint ip\n[port]: endpoint port\n[message]\n";
        while(1)
        {
            std::string command;
            std::cin>>command;

            if(command=="help")
                std::cout<<"commands:\nhelp: show this\ngetu:get users from server\nsend\n[ip]\n[port]\n[message]:send message to peer\n";
            if(command=="getu")
                mSocket->send_to(boost::asio::buffer(mParsed.data(),mParsed.size()), server_endpoint);
            if(command=="send")
            {
                try{
                    std::string ip;
                    int port;
                    std::string msg;
                    std::cout<<"ip:";
                    std::cin>>ip;
                    std::cout<<"port:";
                    std::cin>>port;
                    std::cout<<"message:";
                    std::string tmp;
                    std::cin>>tmp;
                    msg = tmp;
                    msg+=": ";
                    msg+=user;

                    udp::endpoint client_endpoint(boost::asio::ip::address_v4::from_string(ip), port);
                    mSocket->send_to(boost::asio::buffer(msg,msg.size()), client_endpoint);
                }
                catch(std::exception& e)
                {
                    std::cout<<"client nao esta mais conectado no servidor\n";
                }
            }
        }
    }
    catch (std::exception& e)
    {
        std::cerr <<"asfsdfsdfsd"<< e.what() << std::endl;
    }

    return 0;
}
